/*===========================================================================
  Copyright (C) 2013-2014 by the Okapi Framework contributors
-----------------------------------------------------------------------------
  This library is free software; you can redistribute it and/or modify it 
  under the terms of the GNU Lesser General Public License as published by 
  the Free Software Foundation; either version 2.1 of the License, or (at 
  your option) any later version.

  This library is distributed in the hope that it will be useful, but 
  WITHOUT ANY WARRANTY; without even the implied warranty of 
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 
  General Public License for more details.

  You should have received a copy of the GNU Lesser General Public License 
  along with this library; if not, write to the Free Software Foundation, 
  Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

  See also the full LGPL text here: http://www.gnu.org/copyleft/lesser.html
===========================================================================*/

package net.sf.okapi.lib.xliff2.core;

import net.sf.okapi.lib.xliff2.InvalidParameterException;
import net.sf.okapi.lib.xliff2.metadata.Metadata;
import net.sf.okapi.lib.xliff2.validation.Validation;

/**
 * Implements the {@link IWithInheritedData}, {@link IWithExtAttributes}, {@link IWithExtElements},
 * {@link IWithNotes}, {@link IWithMetadata} and {@link IWithValidation} interfaces.
 * Also provide methods for type and name access.
 */
class CompleteData extends InheritedDataWithExtAttributes
	implements IWithNotes, IWithMetadata, IWithValidation, IWithExtElements {

	private Notes notes;
	private Metadata metadata;
	private Validation validation;
	private ExtElements xelems;
	private String name;
	private String type;

	/**
	 * Creates an empty {@link CompleteData} object.
	 */
	protected CompleteData () {
		// Nothing to do
	}
	
	/**
	 * Copy constructor.
	 * @param original the original object to duplicate.
	 */
	protected CompleteData (CompleteData original) {
		super(original);
		if ( original.getNoteCount() > 0 ) {
			notes = new Notes(original.notes);
		}
		if ( original.hasMetadata() ) {
			metadata = new Metadata(original.metadata);
		}
		if ( original.hasValidation() ) {
			validation = new Validation(original.validation, false);
		}
		if ( original.hasExtElements() ) {
			xelems = new ExtElements(original.xelems);
		}
		name = original.name;
		type = original.type;
	}
	
	@Override
	public ExtElements getExtElements () {
		if ( xelems == null ) xelems = new ExtElements();
		return xelems;
	}

	@Override
	public boolean hasExtElements () {
		if ( xelems == null ) return false;
		return (xelems.size() > 0);
	}

	@Override
	public ExtElements setExtElements (ExtElements elements) {
		this.xelems = elements;
		return getExtElements();
	}

	@Override
	public void addNote (Note note) {
		if ( notes == null ) notes = new Notes();
		notes.add(note);
	}

	@Override
	public Notes getNotes () {
		if ( notes == null ) notes = new Notes();
		return notes;
	}
	
	@Override
	public int getNoteCount () {
		if ( notes == null ) return 0;
		return notes.size();
	}
	
	@Override
	public Note getNote (String fragIdOrId) {
		if ( notes == null ) return null;
		return notes.get(fragIdOrId);
	}

	/**
	 * Gets the name for this group.
	 * @return the name for this group (can be null).
	 */
	public String getName () {
		return name;
	}
	
	/**
	 * Sets the name for this group.
	 * @param name the new name to set (can be null).
	 */
	public void setName (String name) {
		this.name = name;
	}

	/**
	 * Gets the type for this group.
	 * @return the type for this group (can be null).
	 */
	public String getType () {
		return type;
	}
	
	/**
	 * Sets the type for this group.
	 * The value must have a prefix (for both unit and group elements)
	 * @param type the new type to set (can be null).
	 */
	public void setType (String type) {
		if ( type != null ) {
			int n = type.indexOf(':');
			if (( n == -1 ) || ( n == 0 ) || ( n == type.length()-1 )) {
				throw new InvalidParameterException(String.format("Invalid value '%s' for type.", type));
			}
			if ( type.startsWith("xlf:") ) {
				// No values define for 2.0
				throw new InvalidParameterException("The prefix 'xlf' is reserved.");
			}
		}
		this.type = type;
	}

	@Override
	public boolean hasMetadata () {
		if ( metadata == null ) return false;
		return !metadata.isEmpty();
	}

	@Override
	public Metadata getMetadata () {
		if ( metadata == null ) metadata = new Metadata();
		return metadata;
	}

	@Override
	public void setMetadata (Metadata metadata) {
		this.metadata = metadata;
	}

	@Override
	public boolean hasValidation () {
		if ( validation == null ) return false;
		return !validation.isEmpty();
	}

	@Override
	public Validation getValidation () {
		if ( validation == null ) validation = new Validation();
		return validation;
	}

	@Override
	public void setValidation (Validation validation) {
		this.validation = validation;
	}

}
